<?php
namespace Satan\Think\Addons;

use think\App;
use think\facade\Config;
use think\Request;
use think\View;

class ThinkAddons
{
    /**
     * @var App $app think app容器实例
     */
    protected App $app;
    /**
     * @var Request $request think request 实例
     */
    protected Request $request;
    /**
     * @var string $configRange 插件配置作用域
     */
    protected string $configRange = 'addon_config';
    /**
     * @var string $infoRange 插件信息作用域
     */
    protected string $infoRange = 'addon_info.';
    /**
     * @var string $addons_path 插件目录
     */
    public string $addons_path = '';

    /**
     * @var string $addonName 插件标识
     */

    protected string $addonName = '';

    /**
     * @var string $addons_public_path 插件共有目录
     */
    private string $addons_public_path = '';

    public function __construct($name=null)
    {
        $this->app = \app();
        $this->request = $this->app->request;;
        //设置插件公共目录
            $this->addons_public_path = addon_path($name);


        $name = is_null($name) ? $this->getName() : $name;

        //设置插件标识
        $this->addonName = $name;

        // 获取当前插件目录
        $this->addons_path = $this->addons_public_path . $name . DIRECTORY_SEPARATOR;
// 初始化视图模型
        $config = ['view_path' => $this->addons_public_path.'view'.DIRECTORY_SEPARATOR];
        $config = array_merge(Config::get('view'), $config);
        //动态合并
        Config::set($config,'view');
        // 控制器初始化
        if (method_exists($this, '_initialize')) {
            $this->_initialize();
        }
    }

    /**
     * 获取当前模块名
     * @return string
     */
    final public function getName(): string
    {
        if ($this->addonName) {
            return $this->addonName;
        }
        $data = explode('\\', get_class($this));
        return strtolower(array_pop($data));
    }

    /**
     * 读取基础配置信息
     * @param string $name
     * @param bool $force
     * @return array
     */
    final public function getInfo($name = '', $force = false): array
    {
        if (empty($name)) {
            $name = $this->getName();
        }
        if (!$force) {
            $info = Config::get($this->infoRange.$name);
            if ($info) {
                return $info;
            }
        }
        $info = [];
        $info_file = $this->addons_path . 'info.ini';
        if (is_file($info_file)) {
            $info = Config::load($info_file, $this->infoRange.$name);
            $info['url'] = $this->url($name);
        }
        return $info ? $info : [];
    }
    /**
     * 获取插件的配置数组
     * @param string $name 可选模块名
     * @return array
     */
    final public function getConfig($name = '', $force = false): array
    {
        if (empty($name)) {
            $name = $this->getName();
        }
        if (!$force) {
            $config = Config::get($this->configRange.$name);
            if ($config) {
                return $config;
            }
        }
        $config = [];
        $config_file = $this->addons_path . 'config.php';
        if (is_file($config_file)) {
         return Config::load($config_file,$this->configRange.$name);
        }
        return $config;
    }

    /**
     * @param string $url
     * @param array $vars
     * @param bool $suffix
     * @param false $domain
     * @return string
     */
    final public function url(string $url = '', array $vars = [], $suffix = true, $domain = false): string
    {
        return url($url,$vars,$suffix,$domain)->build();
    }

    /**
     * 设置配置数据
     * @param       $name
     * @param array $value
     * @return array
     */
    final public function setConfig($name = '', $value = []): array
    {
        if (empty($name)) {
            $name = $this->getName();
        }
        $config = $this->getConfig($name);
        $config = array_merge($config, $value);
        Config::set($config,$this->configRange.$name);
        return $config;
    }
    /**
     * 设置插件信息数据
     * @param       $name
     * @param array $value
     * @return array
     */
    final public function setInfo($name = '', $value = []): array
    {
        if (empty($name)) {
            $name = $this->getName();
        }
        $info = $this->getInfo($name);
        $info = array_merge($info, $value);
        Config::set($info, $this->infoRange.$name);
        return $info;
    }
    /**
     * 获取完整配置列表
     * @param string $name
     * @return array
     */
    final public function getFullConfig($name = ''): array
    {
        $fullConfigArr = [];
        if (empty($name)) {
            $name = $this->getName();
        }
        $config_file = $this->addons_path . 'config.php';
        if (is_file($config_file)) {
            $fullConfigArr = Config::load($config_file);
        }
        return $fullConfigArr;
    }

    /**
     * 设置插件标识
     * @param $name
     */
    final public function setName($name)
    {
        $this->addonName = $name;
    }

    /**
     * 检查基础配置信息是否完整
     * @return bool
     */
    final public function checkInfo(): bool
    {
        $info = $this->getInfo();
        $info_check_keys = ['name', 'title', 'intro', 'author', 'version', 'state'];
        foreach ($info_check_keys as $value) {
            if (!array_key_exists($value, $info)) {
                return false;
            }
        }
        return true;
    }
    /**
     * 加载模板和页面输出 可以返回输出内容
     * @access public
     * @param string $template 模板文件名或者内容
     * @param array  $vars     模板输出变量
     * @param array  $replace  替换内容
     * @return mixed
     */
    public function fetch($template = '', $vars = [], $replace = [])
    {
        if (!is_file($template)) {
            $template = '/' . $template;
        }

        return \view($template,$vars)->filter(function ($content)use($replace){
            return str_replace(array_keys($replace),array_values($replace),$content);
        });
    }
    public function __toString(): string
    {
        // TODO: Implement __toString() method.
        return '';
    }

    /**
     * 渲染内容输出
     * @access public
     * @param string $content 内容
     * @param array  $vars    模板输出变量
     * @param array  $replace 替换内容
     * @return mixed
     */
    public function display($content, $vars = [], $replace = [])
    {
       return $this->fetch($content,$vars,$replace);
    }

    /**
     * 模板变量赋值
     * @access protected
     * @param mixed $name  要显示的模板变量
     * @param mixed $value 变量的值
     * @return void
     */
    public function assign($name, $value = '')
    {
        \think\facade\View::assign($name,$value);
    }
    //必须实现安装
    public function install():bool
    {
        return true;
    }

    //必须卸载插件方法
    public function uninstall():bool
    {
        return false;
    }
}